package com.base.scanner;

import static android.media.MediaPlayer.MEDIA_ERROR_IO;

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;

import androidx.lifecycle.LifecycleObserver;

import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

public class AudioPlayer implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener,
        LifecycleObserver, MediaPlayer.OnErrorListener {

    public MediaPlayer mediaPlayer;
    private boolean isCompletion = false;
    private boolean isPrepared = false;
    private String voiceUrl;
    private int mSeekOnStart = -1;

    public AudioPlayer() {

    }

    private void initPlayer() {
        try {
            if (mediaPlayer == null) {
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.setOnCompletionListener(this);
                isPrepared = false;
                isCompletion = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private CopyOnWriteArraySet<OnVoicePlayerCallBack> voicePlayerCallBacks = new CopyOnWriteArraySet<>();

    public void addPlayCallBack(OnVoicePlayerCallBack callBack) {
        this.voicePlayerCallBacks.add(callBack);
    }

    public OnVoicePlayerCallBack callBack;

    public void setPlayCallBack(OnVoicePlayerCallBack callBack) {
        this.callBack = callBack;
    }

    public void removePlayCallBack(OnVoicePlayerCallBack callBack) {
        this.voicePlayerCallBacks.remove(callBack);
    }

    public boolean isPlaying() {
        boolean playing = false;
        if (mediaPlayer != null) {
            try {
                playing = mediaPlayer.isPlaying();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return playing;
    }

    public void onPause() {
        if (isPlaying()) {
            pause();
        }
    }

    public void onReset() {
        if (!isPrepared) {
            return;
        }
        onPause();
        if (mediaPlayer != null) {
            try {
                mediaPlayer.seekTo(0);
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
        if (!voicePlayerCallBacks.isEmpty()) {
            for (OnVoicePlayerCallBack callBack : voicePlayerCallBacks) {
                if (callBack != null) {
                    callBack.onAudioReset();
                }
            }
        }
        if (this.callBack != null) {
            callBack.onAudioReset();
        }
    }

    /**
     * 播放
     */
    public void play() {
        isCompletion = false;
        initPlayer();
        if (isPrepared) {
            realPlay();
        } else {
            try {
                mediaPlayer.reset();
                mediaPlayer.setDataSource(voiceUrl);
                mediaPlayer.prepareAsync();
                mediaPlayer.setOnPreparedListener(this);
                mediaPlayer.setOnErrorListener(this);
            } catch (IllegalArgumentException | IllegalStateException | IOException |
                     NullPointerException e) {
                e.printStackTrace();
                onError(mediaPlayer, MEDIA_ERROR_IO, 0);
            }
        }
    }


    private void realPlay() {
        if (this.callBack != null) {
            callBack.onAudioPlaying();
        }
        if (!this.voicePlayerCallBacks.isEmpty()) {
            for (OnVoicePlayerCallBack callBack : voicePlayerCallBacks) {
                if (callBack != null) {
                    callBack.onAudioPlaying();
                }
            }
        }
        try {
            if (mediaPlayer != null) {
                mediaPlayer.start();
            }
            refresh_time_handler.post(refresh_time_Thread);
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
        if (mSeekOnStart > 0) {
            seekTo(mSeekOnStart);
            mSeekOnStart = 0;
        }

    }

    public String getCurrentPlayerUrl() {
        return voiceUrl;
    }

    public void setDataSourceAndPrepareAsync(String voiceUrl) {
        this.voiceUrl = voiceUrl;
    }

    public void seekTo(int progress) {
        isCompletion = false;
        if (mediaPlayer != null) {
            try {
                mediaPlayer.seekTo(progress);
                refresh_time_handler.post(refresh_time_Thread);
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 暂停
     */
    public void pause() {
        refresh_time_handler.removeCallbacks(refresh_time_Thread);
        if (mediaPlayer != null) {
            try {
                mediaPlayer.pause();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }

        if (this.callBack != null) {
            callBack.onAudioPause();
        }
        if (!this.voicePlayerCallBacks.isEmpty()) {
            for (OnVoicePlayerCallBack callBack : voicePlayerCallBacks) {
                if (callBack != null) {
                    callBack.onAudioPause();
                }
            }
        }
    }

    public void release() {
        if (refresh_time_handler != null && refresh_time_Thread != null) {
            refresh_time_handler.removeCallbacks(refresh_time_Thread);
        }

        setDataSourceAndPrepareAsync("");
        if (this.callBack != null) {
            callBack.onAudioReset();
        }
        if (!voicePlayerCallBacks.isEmpty()) {
            for (OnVoicePlayerCallBack callBack : voicePlayerCallBacks) {
                if (callBack != null) {
                    callBack.onAudioReset();
                }
            }
        }
        if (mediaPlayer != null) {
            try {
                mediaPlayer.stop();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
            ThreadPoolManager.getSingleExecutor().execute(() -> {
                if (mediaPlayer != null) {
                    try {
                        mediaPlayer.release();
                        mediaPlayer = null;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    /**
     * 重播
     */
    public void replay() {
        if (mediaPlayer != null) {
            mediaPlayer.seekTo(0);
        }
    }

    /**
     * 播放进度定时器
     */
    private final Handler refresh_time_handler = new Handler();

    private int delaySecondTime = 1000;//进度回调间隔

    private final Runnable refresh_time_Thread = new Runnable() {
        @Override
        public void run() {
            if (isPrepared) {
                if (mediaPlayer == null) {
                    return;
                }
                int duration = mediaPlayer.getDuration();
                int currentPosition = mediaPlayer.getCurrentPosition();
                if (duration > 0) {
                    if (callBack != null) {
                        callBack.onAudioProgress(currentPosition, duration);
                    }
                    if (!voicePlayerCallBacks.isEmpty()) {
                        for (OnVoicePlayerCallBack callBack : voicePlayerCallBacks) {
                            if (callBack != null) {
                                callBack.onAudioProgress(currentPosition, duration);
                            }
                        }
                    }
                    if (duration == currentPosition) {
                        onCompletion(mediaPlayer);
                    }
                }
            }
            if (isPlaying()) {
                int diff = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition();
                if (diff > 0) {
                    refresh_time_handler.postDelayed(refresh_time_Thread, Math.min(diff, delaySecondTime));
                }
            }
        }
    };

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        if (callBack != null) {
            callBack.onAudioError(what, extra);
        }
        if (!voicePlayerCallBacks.isEmpty()) {
            for (OnVoicePlayerCallBack callBack : voicePlayerCallBacks) {
                if (callBack != null) {
                    callBack.onAudioError(what, extra);
                }
            }
        }
        return true;
    }

    @Override
    public void onPrepared(MediaPlayer arg0) {
        isPrepared = true;
        isCompletion = false;
        if (arg0.getDuration() <= 5000) {
            delaySecondTime = 300;
        } else {
            delaySecondTime = 1000;
        }
        realPlay();
        if (callBack != null) {
            callBack.onAudioDuration(arg0.getDuration());
        }
        if (!voicePlayerCallBacks.isEmpty()) {
            for (OnVoicePlayerCallBack callBack : voicePlayerCallBacks) {
                if (callBack != null) {
                    callBack.onAudioDuration(arg0.getDuration());
                }
            }
        }

    }

    @Override
    public void onCompletion(MediaPlayer arg0) {
        isCompletion = true;
        if (mediaPlayer != null) {
            onPause();
            try {
                mediaPlayer.seekTo(0);
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
        refresh_time_handler.removeCallbacks(refresh_time_Thread);
        if (callBack != null) {
            callBack.onAudioCompletion();
        }
        if (!voicePlayerCallBacks.isEmpty()) {
            for (OnVoicePlayerCallBack callBack : voicePlayerCallBacks) {
                if (callBack != null) {
                    callBack.onAudioCompletion();
                }
            }
        }
    }


    /**
     * 从哪里开始播放
     * 目前有时候前几秒有跳动问题，毫秒
     * 需要在startPlayLogic之前，即播放开始之前
     */
    public void setSeekOnStart(int seekOnStart) {
        this.mSeekOnStart = seekOnStart;
    }

    /**
     * 是否准备完毕
     */
    public boolean isPrepared() {
        return isPrepared;
    }

    /**
     * 是否播放完毕
     */
    public boolean isCompletion() {
        return isCompletion;
    }

    public int getCurrentProgress() {
        if (isCompletion) {
            return 0;
        }
        int currentPosition = 0;
        if (mediaPlayer != null) {
            try {
                currentPosition = mediaPlayer.getCurrentPosition();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return Math.max(0, currentPosition);
    }

    public int getMax() {
        int duration = 0;
        if (mediaPlayer != null) {
            try {
                duration = mediaPlayer.getDuration();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return Math.max(duration, 0);
    }
}